深入理解ActivityManagerService-ActivityRecord、TaskRecord、ActivityStack的作用及关系

ActivityManagerService

ActivityManagerService(简称AMS)是Android系统最核心的Binder服务之一,从名称上看好像它只是Activity的管理者,但实际上AMS管理和维护着系统四大组件(Activity,Service,Broadcast,ContentProvider)的相关工作,这个任务非常重要而且异常复杂,在KK中单是AMS一个类的源码行数就高达一万六千多行,可见其内部的任务有多庞大。在这之中,AMS对于Activity的管理任务最为复杂,这可能也是它为什么叫ActivityManagerService的原因吧。AMS对于activity的管理实际上通过三个类来体现,它们分别是ActivityRecord,TaskRecord以及ActivityStack,把握和理解它们之间的关系对于我们理解AMS的工作将会有很大的帮助。因此本篇将会介绍这三者在AMS中的联系和作用。

ActivityRecord

ActivityRecord是应用层Activity组件在AMS中的代表,每一个在应用中启动的Activity,在AMS中都有一个ActivityRecord实例来与之对应,这个ActivityRecord伴随着Activity的启动而创建,也伴随着Activity的终止而销毁。

类结构说明

关于ActivityRecord类,它只是一个简单的类,并没有继承任何其他父类,在它内部存储的都是一些关于Activity组件的相关信息,所以类结构比较简单,下面我将列出它的一些成员进行介绍:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
* An entry in the history stack, representing an activity.
*/
final class ActivityRecord {
final ActivityManagerService service; // owner
final IApplicationToken.Stub appToken; // window manager token
final ActivityInfo info; // all about me
final int launchedFromUid; // always the uid who started the activity.
final String launchedFromPackage; // always the package who started the activity.
final int userId; // Which user is this running for?
final Intent intent; // the original intent that generated us
final ComponentName realActivity; // the intent component, or target of an alias.
final String shortComponentName; // the short component name of the intent
final String resolvedType; // as per original caller;
final String packageName; // the package implementing intent's component
final String processName; // process where this component wants to run
final String taskAffinity; // as per ActivityInfo.taskAffinity
...
int labelRes; // the label information from the package mgr.
int icon; // resource identifier of activity's icon.
int logo; // resource identifier of activity's logo.
int theme; // resource identifier of activity's theme.
int realTheme; // actual theme resource we will use, never 0.
int windowFlags; // custom window flags for preview window.
TaskRecord task; // the task this is in.
Configuration configuration; // configuration activity was last running in
CompatibilityInfo compat;// last used compatibility mode
ActivityRecord resultTo; // who started this entry, so will get our reply
final String resultWho; // additional identifier for use by resultTo.
final int requestCode; // code given by requester (resultTo)
HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
ArrayList<Intent> newIntents; // any pending new intents for single-top mode
ActivityOptions pendingOptions; // most recently given options
HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
UriPermissionOwner uriPermissions; // current special URI access perms.
ProcessRecord app; // if non-null, hosting application
ActivityState state; // current state we are in
...
int launchMode; // the launch mode activity attribute.

}

可以看出ActivityRecord包含了很多信息,我们简单描述下:

  1. appToken :这是一个Binder,而且是Server端的实体,Token即令牌,它一般作为一个标识使用,这个appToken用来在WindowManagerService端标识这个AcitvityRecord,token的实现如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
static class Token extends IApplicationToken.Stub {
final WeakReference<ActivityRecord> weakActivity;

Token(ActivityRecord activity) {
weakActivity = new WeakReference<ActivityRecord>(activity);
}

@Override public void windowsDrawn() {
ActivityRecord activity = weakActivity.get();
if (activity != null) {
activity.windowsDrawn();
}
}

@Override public void windowsVisible() {
ActivityRecord activity = weakActivity.get();
if (activity != null) {
activity.windowsVisible();
}
}

@Override public void windowsGone() {
ActivityRecord activity = weakActivity.get();
if (activity != null) {
activity.windowsGone();
}
}
...
}

可以看到它实际上是一个Token,实现了自IApplicationToken.Stub的方法,内部有个弱引用指向包含它的ActivityRecord实例,从实现来看,appkToken实际上有两个作用,在WMS端标记一个ActivityRecord,同时可以通过该token和AMS进行通信。
2. launchedFromUid和launchedFromPackage 启动该activity的应用uid和包名,比如我们从launcher启动的应用activity,这个对应的就是launcher的uid和包名
3. intent 和 ComponentName intent是启动时候传递的意图对象,ComponentName标记了启动的acitivity组件。
4. packageName和processName 分别代表了activity所属应用的包名和进程名
5. taskAffinity 标记了activity的亲属性,默认情况下为包名,这个成员和该activity所属TaskRecord有关,后面我们具体介绍。
6. logo 和 theme 这些是activity所使用的logo和theme资源标记。
7. task 应用所属TaskRecord,后面介绍。
8. resultTo和requestCode,resultTo也是一个ActivityRecord,它是当前ActivityRecord对应的activity要返回和回复的activity,我们通过startActivityForResult启动一个activity时,往往需要接受来自于启动的activity的返回值,这个resultTo就是负责处理返回值的activity对应的ActivityRecord
9. app 它是一个ProcessRecord,用于描述当前activity所在应用的进程
10. state 它是一个AcitivityState枚举,用于描述当前activity的状态,这些状态被AMS内部使用,ActivityState的定义如下:

1
2
3
4
5
6
7
8
9
10
11
enum ActivityState {
INITIALIZING,
RESUMED,
PAUSING,
PAUSED,
STOPPING,
STOPPED,
FINISHING,
DESTROYING,
DESTROYED
}
  1. launchMode activity的启动模式

ActivityRecord的创建

1
2
3
4
5
6
7
8
9
10
11
12
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
boolean componentSpecified, ActivityRecord[] outActivity) {
...
//为activity创建ActivityRecord
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified, this);
...
}

AcitivtyRecord是在启动activity时候创建的,这里具体是在ActivityStackSupervisor中,关于ActivityStackSupervisor后面再介绍。我们看看ActivityRecord的构造方法中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
ActivityRecord(ActivityManagerService _service, ProcessRecord _caller,
int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
ActivityInfo aInfo, Configuration _configuration,
ActivityRecord _resultTo, String _resultWho, int _reqCode,
boolean _componentSpecified, ActivityStackSupervisor supervisor) {
service = _service;
appToken = new Token(this);//创建了appToken 这个token用来标记activity,token内部持有该ActivityRecord的弱引用
info = aInfo;
launchedFromUid = _launchedFromUid;
launchedFromPackage = _launchedFromPackage;
userId = UserHandle.getUserId(aInfo.applicationInfo.uid);
intent = _intent;
shortComponentName = _intent.getComponent().flattenToShortString();
resolvedType = _resolvedType;
componentSpecified = _componentSpecified;
configuration = _configuration;
resultTo = _resultTo;
resultWho = _resultWho;
requestCode = _reqCode;
state = ActivityState.INITIALIZING;
frontOfTask = false;
launchFailed = false;
stopped = false;
delayedResume = false;
finishing = false;
configDestroy = false;
keysPaused = false;
inHistory = false;
visible = true;
waitingVisible = false;
nowVisible = false;
thumbnailNeeded = false;
idle = false;
hasBeenLaunched = false;
mStackSupervisor = supervisor;

...
}

在构造方法中创建了ActivityRecord的appToken,关于appToken我们前面已经做了介绍。初始的activity状态为ActivityState.INITIALIZING,这里的visible标记的是activity在WMS端对应的window是否需要显示,在构造ActivityRecord时表示我们要启动activity了,这时候也就需要WMS为我们显示窗口,置true。nowVisible表示的是activity当前的窗口显示状态,这时候activity还在创建过程中,还未显示出来,置false。

TaskRecord

TaskRecord即任务栈,或者叫返回栈(back Stack),Task实际上是指执行一个特定任务时和用户进行交互的一组activity,什么意思呢?比如我们为了完成用微信发送消息这个任务,而需要打开首页的联系人列表,然后选择一个联系人进入聊天界面发送消息,这两个activity就可以说是一个Task,但如果我们说要发送图片,那么还会去打开选择照片的activity,这时候Task就是三个activity,所以说Task是一个动态的概念,但不管怎么样,我们总成为它是一组activity的集合,这个集合在AMS中就是TaskRecord,它和数据结构中的Stack结构类似,也是先进后出,当我们打开App中的一个activity1时,它对应的ActivityRecord被添加到TaskRecord中,再在activit1中打开第二个页面activity2,在activity2中打开activity3,同样它们的ActivityRecord也会被添加到TaskRecord,当我们按下返回键,activity3先从TaskRecord中弹出来,依次类推,当task中所有的activity被弹出后,这个task也就销毁了。最终它的结构如下图所示:

TaskRecord结构图

Task切换

一般情况下,我们可以将打开的一个app看做是一个TaskRecord,当我们先后打开app A的两个页面A和B,这时候在其对应的TaskRecord中就有两个ActivityRecord的记录,当我们按下home键后,然后打开另一个app B的C和D页面,这时候app A的TaskRecord就到了后台中,它内部的两个activity此时都处于停止状态,而app B的TaskRecord此时处于前台和用户交互的状态,它的TaskRecord中也有两个ActivityRecord的记录,如果我们再按下home键,点击app A,这时候我们发现app A停留在B页面,也就是说app A的TaskRecord又作为一个整体从后台切换到了前台,它的状态和之前是一样的。系统可以同时管理多个后台的TaskRecord,但是如果用户打开的太多app在后台中,系统可能会回收一部分。

打开多个app时,AMS中就存在了多个TaskRecord,我们可以在这些TaskRecord之间进行切换,当我打开Email应用后可以在编辑Email的过程中打开相册应用来选择图片,选择完成后可以继续回到Email中编辑邮件。这个是Task切换带来的便利。

启动模式launchMode

Android管理activity的方式是在同一个Task中使用先进后出的栈管理方式,默认情况下,我们创建一个Activity就会在TaskRecord中有一个实例,但有些时候我们可能希望当启动一个activity的时候使用TaskRecord中已经存在的实例或者当我们启动一个activity时需要将它放置在单独的一个TaskRecord之中,这时候就需要我们为启动的activity设置启动模式(launchMode)了,所以说launchMode是和TaskRecord相关联的。

有四种不同的启动模式:

  1. standard,这个即是Android默认的启动模式,每打开一个Activity就创建一个实例到Task中,同一个Activity在Task中可以有多个实例。
  2. singleTop,如果一个activity的实例已经在Task栈的顶部,那么当再次打开这个activity时会复用这个实例而不再创建一个新的实例,同时通过onNewIntent传递给这个实例Intent。比如Task已经有四个activityA->B->C->D,D在Task顶部,那么再次打开D页面时,Task依然是A->B->C->D,而在Standard模式下将会是A->B->C-D->D
  3. singleTask,这个是说一个activity的实例在Task只能有一个实例,如果一个activity实例已经在Task中存在,Android系统会直接把Intent路由到Task中存在的Activity实例对象上,会通过调用onNewIntent()方法处理,而非创建一个新的Activity实例对象。并且会把在它之上的其它Activity清理掉。但是如果实例不存在Task中,此时系统将会为比较调用方activity和被调用方activity的taskAffnity,如果一致就将该activity创建一个实例,并加入到已存在的Task中,如果不一致,就为该activity创建一个新的Task,此时activity是作为Task的root activity的。事实上,Task的taskAffinity正是由Task的root activity决定的。
  4. singleInstance,如果设置了该模式,那么在Task中只能有一个该activity的实例。

启动模式不仅可以在AndroidManifest中进行设定,同样的我们可以使用Intent Flags进行设定,一些常见的Flags可以更方便和灵活的处理activity和Task的关系:

  1. FLAG_ACTIVITY_NEW_TASK ,这个标记同singleTask的处理方式
  2. FLAG_ACTIVITY_SINGLE_TOP,这个标记同singleTop的处理方式
  3. FLAG_ACTIVITY_CLEAR_TOP,如果activity的实例已经在当前Task中,那么再启动时,将会将其之上的activity实例都销毁掉。比如Task A->B->C->D,如果在D中启动B添加了该标记,那么会将C和C都从Task销毁掉,如果此时B是默认的启动模式,那么会将B的实例也销毁,并重新创建一个实例添加到Task顶部,如果我们不想它重新创建,可以配合FLAG_ACTIVITY_SINGLE_TOP使用,这样复用顶部的B实例并触发onNewIntent。
  4. FLAG_ACTIVITY_REORDER_TO_FRONT,新启动的Activity将会被放到它所属task的顶部,例如,当Task A->B->C->D,如果D启动B使用了这个标记,B将会排在这个task的最上面,也即现在Task的顺序变成了A,C,D,B。
  5. FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET 这个标记将会在TASK重置时清理对应的Activity,比如Task当前为A->B,A启动B添加了该标记,那么当切换到Home再打开该应用后Task变为A,B被清理。这个其实是在Task中设置了一个还原点,当Task重置时将Task恢复到指定的还原点。

另外在 AndroidManifest的中也可以设置和Task相关属性,下面我们看看几种:

  1. android:allowTaskReparenting
    这个属性定义的是activity具有reparent Task的能力,即标记一个Activity实例在当前应用退居后台后,是否能从启动它的那个Task移动到有共同TaskAffinity的Task,“true”表示可以移动,“false”表示它必须呆在当前应用的task中,默认值为false。下面通过一个例子说明这种情况:
    比如App A 有一个Activity:MainActivity,App B有两个Activity:BMainActivity和SecondActivity,其中SecondActivity定义了该属性为true,当我们在App A中的MainActivity中启动App B的SecondActivity后,此时A的Task为MainActivity->SecondActivity,注意此时MainActivity和SecondActivity的TaskAffinity并不是相同的,他们为各自的包名。如果此时按Home键回到Launcher,再启动App B后,会发现此时的页面是SecondActivity,也就是说SecondActivity从原来App A的Task移动到了和他TaskAffinity相同的Task中即App B的Task。

  2. android:clearTaskOnLaunch
    如果设置了这个属性为true,每次用户重新启动这个应用时,都只会看到Root Activity,task中的其他Activity都会被清除出栈。这个属性也只对Root Activity有效。

  3. android:alwaysRetainTaskState
    这个属性是让Task保持原来的状态,true表示保持,false不能够保持,此属性也只对Root Activity有效,一般情况下,如果Task切换到后台后太久系统会对Task进行清理,除了Root Activity其他Activity都会被清理。但如果设置了该属性为true,则可以保持上次操作的界面。

  4. android:noHistory
    这个属性设置为true后,则Activity将不会被记录到Task的history列表中,那么就是说,这个Activity不可见,那么它实际上就和销毁了一样,因为AMS没有它的相关信息。

TaskRecord的实现

了解了Task的相关知识,接下来我们看看它是如何在AMS中实现的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
final class TaskRecord extends ThumbnailHolder {
final int taskId; // Unique identifier for this task. //Task栈的比唯一标志
final String affinity; // The affinity name for this task, or null.
Intent intent; // The original intent that started the task.
Intent affinityIntent; // Intent of affinity-moved activity that started this task.
ComponentName origActivity; // The non-alias activity component of the intent.
ComponentName realActivity; // The actual activity component that started the task.
int numActivities; // Current number of activities in this task.
long lastActiveTime; // Last time this task was active, including sleep.
boolean rootWasReset; // True if the intent at the root of the task had
// the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
boolean askedCompatMode;// Have asked the user about compat mode for this task.

String stringName; // caching of toString() result.
int userId; // user for which this task was created

int numFullscreen; // Number of fullscreen activities.

/** List of all activities in the task arranged in history order */
final ArrayList<ActivityRecord> mActivities = new ArrayList<ActivityRecord>();//以历史序排列的所有activities

/** Current stack */
ActivityStack stack;

/** Takes on same set of values as ActivityRecord.mActivityType */
private int mTaskType;

/** Launch the home activity when leaving this task. */
boolean mOnTopOfHome = false;

TaskRecord(int _taskId, ActivityInfo info, Intent _intent) {
taskId = _taskId;
affinity = info.taskAffinity;
setIntent(_intent, info);
}
...
}

在AMS中,Task是通过TaskRecord类来描述的,它的成员相对ActivityRecord要少很多,这里我们介绍下:

  1. taskId,这个是TaskRecord的一个唯一标记
  2. affnity,亲属性的名称,同一个Task的ativity有相同的taskAffinity,它是由Task的Root Activity的taskAffinity决定的。
  3. Intent,启动这个Task的源activity对应的Intent,也即是启动root activity的Intent。
  4. numActivities,这个是当前Task中的activity数目。
  5. numFullscreen 全屏activity的个数
  6. mActivities 维护的ActivityRecord实例,这个代表的就是Activity,可见TaskRecord栈结构是通过ArrayList来体现的。
  7. stack ,所属的ActivityStack,关于ActivityStack我们后面介绍

TaskRecord的创建

一般情况下,在启动App的第一个activity时,AMS为其创建一个TaskRecord任务栈,当然启动后也可能创建新的TaskRecord,比如我们启动singleTask的Activity,而且为该Activity指定了和包名不同的taskAffinity,这时候也会为该activity创建一个新的TaskRecord,所有一个App是可能有多个TaskRecord存在的,这取决于应用的使用场景和需求。

我们按照分析的逻辑看看AMS中是如何实现为TaskRecord创建的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {

boolean addingToTask = false;
TaskRecord reuseTask = null;
...
ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
? findTaskLocked(r)
: findActivityLocked(intent, r.info);
...
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
...
if (reuseTask == null) {
r.setTask(targetStack.createTaskRecord(getNextTaskId(),
newTaskInfo != null ? newTaskInfo : r.info,
newTaskIntent != null ? newTaskIntent : intent,
true), null, true);//创建新的taskRecord
}
}
}

}

当启动模式设定为singleTask后我们通过findTaskLocked来为启动的Activity寻找TaskRecord,如果找到则返回它顶部的Activity对应的ActivityRecord。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
ActivityRecord findTaskLocked(ActivityRecord r) {
if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + r);
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
if (!r.isApplicationActivity() && !stack.isHomeStack()) {
if (DEBUG_TASKS) Slog.d(TAG, "Skipping stack: " + stack);
continue;
}
final ActivityRecord ar = stack.findTaskLocked(r);
if (ar != null) {
return ar;
}
}
if (DEBUG_TASKS) Slog.d(TAG, "No task found");
return null;
}

/**
* Returns the top activity in any existing task matching the given
* Intent. Returns null if no such task is found.
*/
ActivityRecord findTaskLocked(ActivityRecord target) {
Intent intent = target.intent;//要启动Activity的Intent
ActivityInfo info = target.info;
ComponentName cls = intent.getComponent();
if (info.targetActivity != null) {
cls = new ComponentName(info.packageName, info.targetActivity);
}
final int userId = UserHandle.getUserId(info.applicationInfo.uid);

if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + target + " in " + this);
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {//遍历TaskRecord
final TaskRecord task = mTaskHistory.get(taskNdx);
if (task.userId != userId) {
// Looking for a different task.
if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": different user");
continue;
}
final ActivityRecord r = task.getTopActivity();//获取taskRecord顶部的activity
if (r == null || r.finishing || r.userId != userId ||
r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": mismatch root " + r);
continue;
}

if (DEBUG_TASKS) Slog.d(TAG, "Comparing existing cls="
+ r.task.intent.getComponent().flattenToShortString()
+ "/aff=" + r.task.affinity + " to new cls="
+ intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
if (task.affinity != null) {//首先根据亲属性taskAffinity匹配,相等的就是匹配的
if (task.affinity.equals(info.taskAffinity)) {
if (DEBUG_TASKS) Slog.d(TAG, "Found matching affinity!");
return r;
}
} else if (task.intent != null && task.intent.getComponent().equals(cls)) {//否则启动的就是栈顶activity
if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
//dump();
if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
+ r.intent);
return r;
} else if (task.affinityIntent != null
&& task.affinityIntent.getComponent().equals(cls)) {
if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
//dump();
if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
+ r.intent);
return r;
} else if (DEBUG_TASKS) {
Slog.d(TAG, "Not a match: " + task);
}
}

return null;//未找到就返回null
}

在findTaskLocked中,我们会比较要启动的Activity和Task的affinity,如果匹配就返回TaskRecord顶部的ActivityRecord,如果最终没找到则返回null。如果返回值intentActivity为null,那么
addingToTask和reuseTask都不会设置,这时候会通过createTaskRecord创建TaskRecord并设置到ActivityRecord之中。

TaskRecord的复用

事实上大多数情况,Activity都会复用TaskRecord,也就是说Activity会添加到相同的TaskRecord之中,除了应用第一次启动或者taskAffinity不同之外。如果上一步中通过findTaskLocked返回的intentActivity不为null,这表示我们为启动模式为singleTask的activity找到了一个可复用的TaskRecord。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
? findTaskLocked(r)
: findActivityLocked(intent, r.info);
if (intentActivity != null) {//找到对应TaskRecord栈顶的ActivityRecord
if (r.task == null) {
r.task = intentActivity.task;//设置r的TaskRecord为该Task
}
}
}

if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
...
} else if (sourceRecord != null) {//针对其他启动模式的复用TaskRecord
TaskRecord sourceTask = sourceRecord.task;
targetStack = sourceTask.stack;
...
r.setTask(sourceTask, sourceRecord.thumbHolder, false);
}
}

ActivityStack

ActivityStack的说法听起来很容易和我们常说的任务栈混淆,很多人可能看到它的第一个反应是它就是我们的任务栈,然而并非如此,我们知道系统中可能同时有多个Task,一般前台就一个Task和用户进行交互,而后台中可能有多个Task存在,前后台的Task可以进行切换,AMS为了方便的管理这些Task而引入了ActivityStack,在ActivityStack内部通过ArrayList维护了一组TaskRecord。一般来说Launcher的Task属于单独的一个ActivityStack,称为Home Activity Stack,System UI如rencentActivity的Task属于一个单独ActivityStack,其他App的Task属于另一个ActivityStack。

结构

下面我们看看ActivityStack的结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
final class ActivityStack {
...
final ActivityManagerService mService;//AMS引用
final WindowManagerService mWindowManager;//WMS引用

/**
* The back history of all previous (and possibly still
* running) activities. It contains #TaskRecord objects.
*/
private ArrayList<TaskRecord> mTaskHistory = new ArrayList<TaskRecord>();

/**
* List of running activities, sorted by recent usage.
* The first entry in the list is the least recently used.
* It contains HistoryRecord objects.
*/
final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<ActivityRecord>();

...

/**
* This is the last activity that we put into the paused state. This is
* used to determine if we need to do an activity transition while sleeping,
* when we normally hold the top activity paused.
*/
ActivityRecord mLastPausedActivity = null;//记录了上次切换ActivityStack后被暂停的Activity

/**
* Current activity that is resumed, or null if there is none.
*/
ActivityRecord mResumedActivity = null;//当前正在运行的activity,可以为null表示当前运行的activity不在该ActivityStack中

final int mStackId;

/** Run all ActivityStacks through this */
final ActivityStackSupervisor mStackSupervisor;//ActivityStack的管家

...

}

从其成员中我们可以看出ActivityStack维护了一组TaskRecord,以及一组最近使用的Activities,还有上次切换ActivityStack被暂停的Activity,和TaskRecord类似,多个ActivityStack同样是可以进行切换的,比如我们从桌面Launcher点击app后,会从Launcher所在的ActivityStack切换到app所在的ActivityStack,mResumedActivity表示正在运行的activity,它也可以是null,当为null时表示当前运行的Activity不在该ActivityStack。同样的,在ActivityStack中通过mStackId来唯一的标识一个ActivityStack。

明白了ActivityStack的概念和用途,我们看看ASM是如何管理它的。在AMS中通过ActivityStackSupervisor来管理这些ActivityStack,从而间接的管理着TaskRecord,在ActivityStackSupervisor内部通过mHomeStack和mStacks管理着所有ActivityStack,其中mHomeStack是Launcher的TaskRecord所在的ActivityStack,而mStacks是其他的ActivityStack,它是一个ArrayList

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
...
/** Run all ActivityStacks through this */
ActivityStackSupervisor mStackSupervisor;
...
//在SystemServer启动时候 调用该main方法
public static final Context main(int factoryTest) {
...
ActivityManagerService m = thr.mService;
mSelf = m;
ActivityThread at = ActivityThread.systemMain();
mSystemThread = at;//创建AMS的ActivityThread
Context context = at.getSystemContext();
context.setTheme(android.R.style.Theme_Holo);//系统默认的context主题
m.mContext = context;
m.mFactoryTest = factoryTest;
m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface());

m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper);//创建ActivityStack管家

m.mBatteryStatsService.publish(context);
m.mUsageStatsService.publish(context);
m.mAppOpsService.publish(context);

...
return context;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public final class ActivityStackSupervisor {
final ActivityManagerService mService;
/** Identifier counter for all ActivityStacks */
private int mLastStackId = HOME_STACK_ID;
/** Task identifier that activities are currently being started in. Incremented each time a
* new task is created. */
private int mCurTaskId = 0;

/** The current user */
private int mCurrentUser;

/** The stack containing the launcher app */
private ActivityStack mHomeStack;

/** The non-home stack currently receiving input or launching the next activity. If home is
* in front then mHomeStack overrides mFocusedStack.
* DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */
private ActivityStack mFocusedStack;

/** All the non-launcher stacks */
private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();

/** List of activities that are waiting for a new activity to become visible before completing
* whatever operation they are supposed to do. */
final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();

/** List of activities that are ready to be stopped, but waiting for the next activity to
* settle down before doing so. */
final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();

/** List of activities that are ready to be finished, but waiting for the previous activity to
* settle down before doing so. It contains ActivityRecord objects. */
final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();

/** List of activities that are in the process of going to sleep. */
final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>();

...
}
  1. mLastStackId是所有ActivityStack的计数,这个在创建ActivityStack使用来计算stackId
  2. mCurTaskId 指当前前台的ActivityStatck对应的stackId
  3. mHomeStack 这个是launcher的TaskRecord所在的ActivityStack。
  4. mStacks 所有非Launcher的ActivityStack。这是一个ArrayList,因为非Launcher的ActivityStack可能有多个。
  5. 除了以上成员,ActivityStackSupervisor还维护着多组ActivityRecord的集合,这些分别用来记录那些等待显示,或者正在停止或销毁的Activity。

创建过程

同样的ActivityStack也是按需创建的

1
2
3
4
5
6
7
8
9
10
11
final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
...
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
targetStack = adjustStackFocus(r);

}
...
}

实际上ActivityStack的创建时在Launcher启动时候进行的,而且是在系统启动后启动的第一个app,这个app在启动第一个Activity的时候在AMS还未有非Launcher的ActivityStack,所以需要创建一个。后面的App启动时就会找到这个ActivityStack。创建时通过ActivityStackSupervisor的adjustStackFocus方法,这个方法为要启动的Acitivity寻找前台的ActivityStack,即mFocusedStack。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java
ActivityStack adjustStackFocus(ActivityRecord r) {
final TaskRecord task = r.task;
if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
if (task != null) {
final ActivityStack taskStack = task.stack;
if (mFocusedStack != taskStack) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
"adjustStackFocus: Setting focused stack to r=" + r + " task=" + task);
mFocusedStack = taskStack.isHomeStack() ? null : taskStack;
} else {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
"adjustStackFocus: Focused stack already=" + mFocusedStack);
}
return taskStack;
}
//如果已经有一个Focused stack直接返回即可
if (mFocusedStack != null) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
"adjustStackFocus: Have a focused stack=" + mFocusedStack);
return mFocusedStack;
}

for (int stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
ActivityStack stack = mStacks.get(stackNdx);
if (!stack.isHomeStack()) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
"adjustStackFocus: Setting focused stack=" + stack);
mFocusedStack = stack;
return mFocusedStack;
}
}
//如果没有Focused Stack就创建一个
// Time to create the first app stack for this user.
int stackId =
mService.createStack(-1, HOME_STACK_ID, StackBox.TASK_STACK_GOES_OVER, 1.0f);
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
" stackId=" + stackId);
mFocusedStack = getStack(stackId);
return mFocusedStack;
}
return mHomeStack;
}

在adjustStackFocus方法中,对于应用Task,如果ActivityRecord对应的TaskRecord所属的ActivityStack不是当前的mFocusedStack,则将其所属的ActivityStack作为mFoucnedStack返回则直接返回,否则如果此时TaskRecord还未创建,如果mFocusedStack已经不为null,则直接返回,否则会从当前的mStacks找到一个非Home Stack作为mFocusedStack返回,如果以上都不满足,则为当前系统创建一个ActivityStack作为mFocusedStack返回。这是通过调用AMS的createStack方法来完成的结果返回stackId。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 @Override
public int createStack(int taskId, int relativeStackBoxId, int position, float weight) {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
"createStack()");
if (DEBUG_STACK) Slog.d(TAG, "createStack: taskId=" + taskId + " relStackBoxId=" +
relativeStackBoxId + " position=" + position + " weight=" + weight);
synchronized (this) {
long ident = Binder.clearCallingIdentity();
try {
int stackId = mStackSupervisor.createStack();
mWindowManager.createStack(stackId, relativeStackBoxId, position, weight);
if (taskId > 0) {
moveTaskToStack(taskId, stackId, true);
}
return stackId;
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}

createStack是作为AMS的Binder接口提供给使用者的,这里会进一步通过ActivityStackSupervisor的createStack方法创建。

1
2
3
4
5
6
7
8
9
10
11
12
int createStack() {
while (true) {
if (++mLastStackId <= HOME_STACK_ID) {
mLastStackId = HOME_STACK_ID + 1;
}
if (getStack(mLastStackId) == null) {
break;
}
}
mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
return mLastStackId;
}

通过mLaskStackId来计算要创建的ActivityStack对应的id,然后将新创建的实例添加到mStacks中。

Task切换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
...
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
// If bring to front is requested, and no result is requested, and
// we can find a task that was started with this same
// component, then instead of launching bring that one to the front.
if (r.resultTo == null) {
// See if there is a task to bring to the front. If this is
// a SINGLE_INSTANCE activity, there can be one and only one
// instance of it in the history, and it is always in its own
// unique task, so we do a special search.
ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
? findTaskLocked(r)
: findActivityLocked(intent, r.info);
if (intentActivity != null) {//找到对应TaskRecord栈顶的ActivityRecord
if (r.task == null) {
r.task = intentActivity.task;//设置r的TaskRecord为该Task
}
targetStack = intentActivity.task.stack;//设置ActivityStack为该Stack
...
// If the target task is not in the front, then we need
// to bring it to the front... except... well, with
// SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
// to have the same behavior as if a new instance was
// being started, which means not bringing it to the front
// if the caller is not itself in the front.
final ActivityStack lastStack = getLastStack();
ActivityRecord curTop = lastStack == null?
null : lastStack.topRunningNonDelayedActivityLocked(notTop);//取到它顶部的ActivityRecord
if (curTop != null && (curTop.task != intentActivity.task ||
curTop.task != lastStack.topTask())) {//比较当前的task和复用的task 如果不是同一个就需要将复用的task移动到前端
r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
if (sourceRecord == null || (sourceStack.topActivity() != null &&
sourceStack.topActivity().task == sourceRecord.task)) {
// We really do want to push this one into the
// user's face, right now.
movedHome = true;
targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
...
}
}

}
}
}
...
}

Task的切换同样是在startActivityUncheckedLocked中进行的,首先我们通过findTaskLocked为要启动的activity寻找一个合适的TaskRecord,通过initActivity标识,找到后这个TaskRecord就是要切换到前台的Task,通过getLastStack取到上次切换的ActivityStack,然后取到它顶部的ActivityRecord,对于Launcher启动来说,这个就是非Launcher Stack,它顶部的Task可能不是initAcitivty标识的那个,因为可能之前我们启动的app的TaskRecord和它是不同的,即curTop.task != intentActivity.task,那么这时候我们需要为r设置Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT,同时通过moveTaskToFrontLocked将Task移动到ActivityStack的顶部。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {

final int numTasks = mTaskHistory.size();//task的数目
final int index = mTaskHistory.indexOf(tr);//当前tr在Stack中的位置
...
mStackSupervisor.moveHomeStack(isHomeStack());

// Shift all activities with this task up to the top
// of the stack, keeping them in the same internal order.
insertTaskAtTop(tr);//移动Task到Stack顶部

...

mWindowManager.moveTaskToTop(tr.taskId);

mStackSupervisor.resumeTopActivitiesLocked();
...
}

moveTaskToFrontLocked通过insertTaskAtTop将TaskRecord移动到顶部

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void insertTaskAtTop(TaskRecord task) {
// If this is being moved to the top by another activity or being launched from the home
// activity, set mOnTopOfHome accordingly.
ActivityStack lastStack = mStackSupervisor.getLastStack();
final boolean fromHome = lastStack == null ? true : lastStack.isHomeStack();
if (!isHomeStack() && (fromHome || topTask() != task)) {
task.mOnTopOfHome = fromHome;
}

mTaskHistory.remove(task);//先删除
// Now put task at top.
int stackNdx = mTaskHistory.size();
if (task.userId != mCurrentUser) {//push非当前用户task到当前task的后面
// Put non-current user tasks below current user tasks.
while (--stackNdx >= 0) {
if (mTaskHistory.get(stackNdx).userId != mCurrentUser) {
break;
}
}
++stackNdx;
}
mTaskHistory.add(stackNdx, task);
}

insertTaskAtTop先从mTaskHistory中删除该TaskRecord,然后计算添加的位置stackNdx,最后添加到mTaskHistory中,这里最顶部的Task一般存放在最末尾。

总结

从以上的分析中,我们知道了ActivityRecord、TaskRecord以及ActivityStack之间的关系及作用,它们之间的组织关系实际上是包含的关系,即AcitivtyStack包含了TaskRecord的集合,TaskRecord包含着ActivityRecord的集合,同时反向的,ActivityRecord中记录了它所属的TaskRecord,TaskRecord记录着它所属的ActivityStack。他们三者贯穿AMS管理Activity的整个逻辑处理,其中ActivityRecord是Activity组件在AMS中的存在的形式,它和Activity实例是一一对应的关系(注意这里描述的是实例),TaskRecord用于描述Task,即一组Activity,这组Activity以栈的形式组织起来,每个启动的Activity即ActivityRecord都应该要有所属的TaskRecord。ActivityStack是系统中用于管理TaskRecord的,系统中可能有多组ActivityStack,大体可以分为Launcher ActivityStack和非Launcher ActivityStack,我们启动的App对应的TaskRecord由非Launcher ActivityStack管理,它是在系统启动第一个app时创建的。

以上都是个人的理解,有描述不当的地方,烦请不吝赐教~

参考

Understand Tasks and Back Stack
https://developer.android.com/guide/components/activities/tasks-and-back-stack

AOSP

坚持原创技术分享,您的支持将鼓励我继续创作!